package com.zwd.cases.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;

import java.io.*;

/**
 * @Description 通过FTP上传文件
 * @Author zhengwd, 参考https://www.cjavapy.com/article/384/
 * @Date 2022/5/27 14:55
 **/
@Slf4j
public class FTPUtil {

    public static void main(String[] args) throws FileNotFoundException {
        //  本方法参考地址： https://www.cjavapy.com/article/384/
        //  文件内容是乱码（文件被破坏问题）原因参考地址： https://codeleading.com/article/18255062819/
        //  如果你本地没有ftp服务器，可以参照搭建： https://www.cnblogs.com/popfisher/p/7992036.html
        //  可以通过任意文件夹地址访问，查看ftp服务器： ftp://你的服务器IP/

        // 服务器IP（你的服务器IP）
        String hostname = "你的服务器IP";
        // 端口号
        int port = 21;
        // 登录用户名
        String username = "你的登录用户名";
        // 登录密码
        String password = "你的登录密码";
        // 文件转存文件夹路径
        String workingPath = "/";

        // 文件存储目标路径（改成你的路径+文件名）
//        String str = "C:\\Users\\86178\\Desktop\\sourceFileName.pdf";

        // 测试用
        String contextPath = getContextPath();
        contextPath = contextPath.replace("target/test-classes/", "");
        String str = contextPath + "src/test/java/com/zwd/cases/demo/file/test/sourceFileName.pdf";
        System.out.println(str);

        InputStream fileInputStream = new FileInputStream(new File(str));
        String saveName = "targetFileName.pdf";
        System.out.println(FTPUtil.upload( hostname, port, username, password, workingPath, fileInputStream, saveName));
    }

    /**
     * 设置私有不能实例化
     */
    private FTPUtil() {}

    /**
     * 上传
     *
     * @param hostname
     * @param port
     * @param username
     * @param password
     * @param workingPath 服务器的工作目录
     * @param inputStream 文件的输入流
     * @param saveName    要保存的文件名
     * @return
     */
    public static boolean upload(String hostname, int port, String username, String password, String workingPath, InputStream inputStream, String saveName) {
        boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        // 1、连接ftp
        if (connect(ftpClient, hostname, port, username, password)) {
            try {
                // 2.检查工作目录是否存在
                if (ftpClient.changeWorkingDirectory(workingPath)) {
                    // 3.检查是否上传成功
                    if (storeFile(ftpClient, saveName, inputStream)) {
                        flag = true;
                        // 4.完成任务，断开ftp
                        disconnect(ftpClient);
                    }
                }
            } catch (IOException e) {
                log.error("工作目录不存在");
                e.printStackTrace();
                // 4.完成任务，断开ftp
                disconnect(ftpClient);
            }
        }
        return flag;
    }

    /**
     * 断开连接
     *
     * @param ftpClient
     * @throws Exception
     */
    public static void disconnect(FTPClient ftpClient) {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.disconnect();
                log.error("已关闭连接");
            } catch (IOException e) {
                log.error("没有关闭连接");
                e.printStackTrace();
            }
        }
    }

    /**
     * 测试是否能连接
     *
     * @param ftpClient
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @return 返回真则能连接
     */
    public static boolean connect(FTPClient ftpClient, String hostname, int port, String username, String password) {
        boolean flag = false;
        try {
            ftpClient.connect(hostname, port);

            // 原文章作者是将编码格式设置放置在这里的，我实际使用的时候，
            //  在自己的ftp服务器是没问题，可能本地兼容utf-8，但是远程（其他人）服务器就会出现彩色乱码
//            ftpClient.enterLocalPassiveMode();
//            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//            ftpClient.setControlEncoding("UTF-8");

            if (ftpClient.login(username, password)) {
                // 查了一些文章，需要ftp登录成功后再设置编码格式，否则编码格式无效，可能会出现文件内容损坏，例如彩色乱码之类的
                ftpClient.enterLocalPassiveMode();
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftpClient.setControlEncoding("UTF-8");

                log.info("连接ftp成功");
                flag = true;
            } else {
                log.error("连接ftp失败，可能用户名或密码错误");
                try {
                    disconnect(ftpClient);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            log.error("连接失败，可能ip或端口错误");
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 上传文件
     *
     * @param ftpClient
     * @param saveName        全路径。如/home/public/a.txt
     * @param fileInputStream 输入的文件流
     * @return
     */
    public static boolean storeFile(FTPClient ftpClient, String saveName, InputStream fileInputStream) {
        boolean flag = false;
        try {
            if (ftpClient.storeFile(saveName, fileInputStream)) {
                flag = true;
                log.error("上传成功");
                disconnect(ftpClient);
            }
        } catch (IOException e) {
            log.error("上传失败");
            disconnect(ftpClient);
            e.printStackTrace();
        }
        return flag;
    }

    public static boolean storeFileByConnOne(FTPClient ftpClient, String saveName, InputStream fileInputStream) {
        boolean flag = false;
        try {
            if (ftpClient.storeFile(saveName, fileInputStream)) {
                flag = true;
                log.error("上传成功");
                disconnect(ftpClient);
            }
        } catch (IOException e) {
            log.error("上传失败");
            disconnect(ftpClient);
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 获取上下文路径
     * @return
     */
    private static String getContextPath() {
        return PdfUtil.class.getResource("/").getPath();
    }
}
